
#include <string.h>

#include "../lib/type.h"
#include "../lib/fifo.h"
#include <jxos_config.h>
#include "jxos_msg.h"
#if (JXOS_MALLOC_ENABLE == 1)
#include "jxos_malloc.h"
#endif
#if (JXOS_REGISTRY_ENABLE == 1)
#include "jxos_registry.h"
#endif

#if (JXOS_MSG_ENABLE == 1)
typedef struct
{
	FIFO_ST msg;
    uint8_t item_size;
} MSG_QUEUE_STRUCT;

static MSG_QUEUE_STRUCT msg_queue_list[MSG_QUEUE_MAX];
static uint8_t msg_queue_count = 0;

#if (JXOS_MALLOC_ENABLE == 1)
JXOS_MALLOC_MEM_POOL_STRUCT msg_queue_mem_pool;
#endif

void jxos_msg_init(void)
{
	uint8_t i;
#if (JXOS_MALLOC_ENABLE == 1)
    msg_queue_mem_pool.mem_pool = (void*)msg_queue_list;
    msg_queue_mem_pool.len = sizeof(MSG_QUEUE_STRUCT)*MSG_QUEUE_MAX;
    msg_queue_mem_pool.offset = 0;
#endif
	msg_queue_count = 0;
	for(i = 0; i < MSG_QUEUE_MAX; i++){
		msg_queue_list[i].item_size = 0;
	}
}

JXOS_MSG_HANDLE jxos_msg_create(uint8_t* queue_space,
						uint16_t queue_space_len,
						uint8_t item_size,
						const char* name)
{
#if (JXOS_MALLOC_ENABLE == 1)
    MSG_QUEUE_STRUCT* h = 0;
    if(jxos_malloc_set_mem_pool(&msg_queue_mem_pool) == 0){
        while(1);
    }
#endif
    if((queue_space == 0)
        ||(queue_space_len == 0)
        ||(item_size == 0)
        ||(name == 0)
    ||(queue_space_len < item_size)){
        return 0;
    }
#if (JXOS_MALLOC_ENABLE == 1)
    h = jxos_malloc(sizeof(MSG_QUEUE_STRUCT));
    if(h != 0){
        if(fifo_init((FIFO_ST*)&(h->msg), queue_space_len, queue_space) == 1){
            h->item_size = item_size;
#if (JXOS_REGISTRY_ENABLE == 1)
            jxos_registry_register(name, h);
#endif
            msg_queue_count++;
        }
        else{
            h = 0;
        }
    }
    return (JXOS_MSG_HANDLE)h;
#else
    if(msg_queue_count < MSG_QUEUE_MAX){
        if(fifo_init(&(msg_queue_list[msg_queue_count].msg),queue_space_len, queue_space)){
            msg_queue_list[msg_queue_count].item_size = item_size;
#if (JXOS_REGISTRY_ENABLE == 1)
            jxos_registry_register(name, h);
#endif
            msg_queue_count++;
            return &(msg_queue_list[msg_queue_count]);
        }
        else{
            return 0;            
        }
    }
    else{
        return 0;
    }
#endif
}

//delete

uint8_t jxos_msg_send(JXOS_MSG_HANDLE queue_h, const void* item_to_queue)
{
    MSG_QUEUE_STRUCT* h = queue_h;
#if (JXOS_MALLOC_ENABLE == 1)
    if((queue_h == 0)
       ||((void*)queue_h < (void*)(msg_queue_mem_pool.mem_pool))
       ||((void*)queue_h > (void*)(msg_queue_mem_pool.mem_pool+msg_queue_mem_pool.offset))
        ||(item_to_queue == 0)){
        return 0;
    }
#endif
   return fifo_write_data(&(h->msg), h->item_size, (uint8_t*)item_to_queue);
}


uint8_t jxos_msg_receive(JXOS_MSG_HANDLE queue_h, void* item_buffer)
{
    MSG_QUEUE_STRUCT* h = queue_h;
#if (JXOS_MALLOC_ENABLE == 1)
    if((queue_h == 0)
       ||((void*)queue_h < (void*)(msg_queue_mem_pool.mem_pool))
       ||((void*)queue_h > (void*)(msg_queue_mem_pool.mem_pool+msg_queue_mem_pool.offset))
        ||(item_buffer == 0)){
        return 0;
    }
#endif
    return fifo_read_data(&(h->msg), h->item_size, (uint8_t*)item_buffer);
}

uint8_t jxos_msg_check_empty(JXOS_MSG_HANDLE queue_h)
{
    MSG_QUEUE_STRUCT* h = queue_h;
#if (JXOS_MALLOC_ENABLE == 1)
    if((queue_h == 0)
       ||((void*)queue_h < (void*)(msg_queue_mem_pool.mem_pool))
       ||((void*)queue_h > (void*)(msg_queue_mem_pool.mem_pool+msg_queue_mem_pool.offset))){
        return 0;
    }
#endif
    if(0 == fifo_get_used_len(&(h->msg))){
        return 1;
    }
    else{
        return 0;
    }
}

void jxos_msg_clean_up(JXOS_MSG_HANDLE queue_h)
{
    MSG_QUEUE_STRUCT* h = queue_h;
    fifo_reset(&(h->msg));
}

#if (JXOS_REGISTRY_ENABLE == 1)
JXOS_MSG_HANDLE jxos_msg_get_handle(const char* name)
{
    if(name == 0){
        return 0;
    }
    return (JXOS_MSG_HANDLE)jxos_registry_find(name);
}
#endif

uint8_t jxos_msg_check_empty_all(void)
{
	uint8_t i;
	for(i = 0; i < msg_queue_count; i++){
		if(0 != fifo_get_used_len(&(msg_queue_list[i].msg))){
			return 0;
		}
	}
	return 1;
}
#endif

